Created DatabaseBase::trxTimestamp method and added usage in ActiveUsers query
authorAaron Schulz <aschulz@wikimedia.org>
Tue, 23 Sep 2014 22:38:44 +0000 (15:38 -0700)
committerReedy <reedy@wikimedia.org>
Wed, 24 Sep 2014 22:38:36 +0000 (22:38 +0000)
Change-Id: Iba3c83ce8010583908f9dbaa8348f7226f524793

includes/db/Database.php
includes/specials/SpecialActiveusers.php

index 9b783a9..29642d0 100644 (file)
@@ -272,9 +272,20 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
         * Either a short hexidecimal string if a transaction is active or ""
         *
         * @var string
+        * @see DatabaseBase::mTrxLevel
         */
        protected $mTrxShortId = '';
 
+       /**
+        * The UNIX time that the transaction started. Callers can assume that if
+        * snapshot isolation is used, then the data is *at least* up to date to that
+        * point (possibly more up-to-date since the first SELECT defines the snapshot).
+        *
+        * @var float|null
+        * @see DatabaseBase::mTrxLevel
+        */
+       private $mTrxTimestamp = null;
+
        /**
         * Remembers the function name given for starting the most recent transaction via begin().
         * Used to provide additional context for error reporting.
@@ -419,6 +430,19 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                return $this->mTrxLevel;
        }
 
+       /**
+        * Get the UNIX timestamp of the time that the transaction was established
+        *
+        * This can be used to reason about the staleness of SELECT data
+        * in REPEATABLE-READ transaction isolation level.
+        *
+        * @return float|null Returns null if there is not active transaction
+        * @since 1.25
+        */
+       public function trxTimestamp() {
+               return $this->mTrxLevel ? $this->mTrxTimestamp : null;
+       }
+
        /**
         * Get/set the number of errors logged. Only useful when errors are ignored
         * @param int $count The count to set, or omitted to leave it unchanged.
@@ -3512,6 +3536,7 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                }
 
                $this->doBegin( $fname );
+               $this->mTrxTimestamp = microtime( true );
                $this->mTrxFname = $fname;
                $this->mTrxDoneWrites = false;
                $this->mTrxAutomatic = false;
index 07e1be1..10ab46a 100644 (file)
@@ -339,21 +339,19 @@ class SpecialActiveUsers extends SpecialPage {
                        return false; // exclusive update (avoids duplicate entries)
                }
 
-               $now = time();
+               $nowUnix = time();
+               // Get the last-updated timestamp for the cache
                $cTime = $dbw->selectField( 'querycache_info',
                        'qci_timestamp',
                        array( 'qci_type' => 'activeusers' )
                );
                $cTimeUnix = $cTime ? wfTimestamp( TS_UNIX, $cTime ) : 1;
-               // If a transaction was already started, it might have an old
-               // snapshot, so kludge the timestamp range a few seconds back.
-               $cTimeUnix -= 5;
 
                // Pick the date range to fetch from. This is normally from the last
                // update to till the present time, but has a limited window for sanity.
                // If the window is limited, multiple runs are need to fully populate it.
-               $sTimestamp = max( $cTimeUnix, $now - $days * 86400 );
-               $eTimestamp = min( $sTimestamp + $window, $now );
+               $sTimestamp = max( $cTimeUnix, $nowUnix - $days * 86400 );
+               $eTimestamp = min( $sTimestamp + $window, $nowUnix );
 
                // Get all the users active since the last update
                $res = $dbw->select(
@@ -381,7 +379,7 @@ class SpecialActiveUsers extends SpecialPage {
                $dbw->delete( 'querycachetwo',
                        array(
                                'qcc_type' => 'activeusers',
-                               'qcc_value < ' . $dbw->addQuotes( $now - $days * 86400 ) // TS_UNIX
+                               'qcc_value < ' . $dbw->addQuotes( $nowUnix - $days * 86400 ) // TS_UNIX
                        ),
                        __METHOD__
                );
@@ -425,11 +423,15 @@ class SpecialActiveUsers extends SpecialPage {
                        }
                }
 
+               // If a transaction was already started, it might have an old
+               // snapshot, so kludge the timestamp range back as needed.
+               $asOfTimestamp = min( $eTimestamp, (int)$dbw->trxTimestamp() );
+
                // Touch the data freshness timestamp
                $dbw->replace( 'querycache_info',
                        array( 'qci_type' ),
                        array( 'qci_type' => 'activeusers',
-                               'qci_timestamp' => $dbw->timestamp( $eTimestamp ) ), // not always $now
+                               'qci_timestamp' => $dbw->timestamp( $asOfTimestamp ) ), // not always $now
                        __METHOD__
                );